package com.services.ws.auditoria;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.services.ws.auditoria.model.ListAbreviatura;
import com.services.ws.auditoria.model.RegistroRequest;
import com.services.ws.auditoria.model.RegistroResponse;

public class RegistroAuditoriaManager {
	private static Logger logger;
	private String 				address;
	private String    			service;
	private static String		url;
	private int 				port;
	private final static String soapEnvelopeStartTag = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://pe/com/claro/esb/services/auditoria/ws\" "
			+ "xmlns:reg=\"http://pe/com/claro/esb/services/auditoria/schemas/registro/Registro.xsd\">  <soapenv:Header/>  <soapenv:Body>";
		
	private final static String soapEnvelopeEndTag = "</soapenv:Body></soapenv:Envelope>";
	
	public RegistroAuditoriaManager(String address, int port, String service) throws Exception {  
		this.address = 	address;
		this.port = 	port;
		this.service = 	service;	
		try{
			logger = LoggerFactory.getLogger(RegistroAuditoriaManager.class);
		} catch (Exception e){
			System.out.println("The RegistroAuditoriaManager logger could not be initialized: " + e.getMessage());
		}
			
		init();
	}
	
	public RegistroResponse registroAuditoria(RegistroRequest registroRequest, final int timeOut) throws SOAPException{
		RegistroResponse registroResponse = new RegistroResponse();
		long startTime = 0L;
        long endTime = 0L;
        StringBuffer msgInfo = new StringBuffer();
        StringBuffer sbRequest = new StringBuffer();
		SOAPConnection conn = null;
		
		sbRequest.append(soapEnvelopeStartTag);
		sbRequest.append("<ws:registroAuditoria>");
		sbRequest.append("<reg:RegistroRequest>");
		sbRequest.append("<reg:transaccion>"+registroRequest.getTransaccion()+"</reg:transaccion>");
		sbRequest.append("<reg:servicio>"+registroRequest.getServicio()+"</reg:servicio>");
		sbRequest.append("<reg:ipCliente>"+registroRequest.getIpCliente()+"</reg:ipCliente>");
		sbRequest.append("<reg:nombreCliente>"+registroRequest.getNombreCliente()+"</reg:nombreCliente>");
		sbRequest.append("<reg:ipServidor>"+registroRequest.getIpServidor()+"</reg:ipServidor>");
		sbRequest.append("<reg:nombreServidor>"+registroRequest.getNombreServidor()+"</reg:nombreServidor>");
		sbRequest.append("<reg:cuentaUsuario>"+registroRequest.getCuentaUsuario()+"</reg:cuentaUsuario>");
		sbRequest.append("<reg:telefono>"+registroRequest.getTelefono()+"</reg:telefono>");
		sbRequest.append("<reg:monto>"+registroRequest.getMonto()+"</reg:monto>");
		sbRequest.append("<reg:texto>"+registroRequest.getTexto()+"</reg:texto>");
		sbRequest.append("</reg:RegistroRequest>");
		sbRequest.append("</ws:registroAuditoria>");
		sbRequest.append(soapEnvelopeEndTag);
		
		logger.info(sbRequest.toString());
		
		try{
			MessageFactory mf = MessageFactory.newInstance();
			MimeHeaders headers = new MimeHeaders();
			SOAPMessage smsg = mf.createMessage(headers, new ByteArrayInputStream(sbRequest.toString().getBytes()));
			conn = SOAPConnectionFactory.newInstance().createConnection();
			startTime = System.currentTimeMillis();
			
			URL endpoint = new URL(null, 
					url, 
	                new URLStreamHandler() {
	                   protected URLConnection openConnection(URL url) throws IOException{  
	                	   URL clone_url = new URL(url.toString());
	                	   HttpURLConnection clone_urlconnection =(HttpURLConnection) clone_url.openConnection(); 
	                       clone_urlconnection.setConnectTimeout(timeOut);
		                   clone_urlconnection.setReadTimeout(timeOut);
	                	   return(clone_urlconnection);
	                   }
	            }); 
			
			SOAPMessage smResponse = conn.call(smsg, endpoint);
			smResponse.writeTo(System.out);
			endTime = System.currentTimeMillis();
			
			if(smResponse != null){
				List<ListAbreviatura> lista=new ArrayList<ListAbreviatura>();
				SOAPBody soapBody = smResponse.getSOAPBody();
				Iterator soapBodyIterator = soapBody.getChildElements();
				soapBody = null;
				if(soapBodyIterator.hasNext()){
					SOAPElement soapBodyElement = (SOAPElement) soapBodyIterator.next();
					Iterator getSubIterator = soapBodyElement.getChildElements();
					if(getSubIterator.hasNext()){
						SOAPElement getSubElement = (SOAPElement) getSubIterator.next();
						Iterator payerIterator = getSubElement.getChildElements();
						while(payerIterator.hasNext()){
							SOAPElement payerElement = (SOAPElement) payerIterator.next();
							Iterator subSubElemet = payerElement.getChildElements();
							System.out.println("payerElement "+payerElement.getTagName()+", "+payerElement.getValue());
							if(payerElement.getTagName().contains("estado")){
								registroResponse.setEstado(payerElement.getValue());
							}else if(payerElement.getTagName().contains("resultado")){
								registroResponse.setResultado(payerElement.getValue());
							}
						}
						
					}
				}
				msgInfo.append("registroAuditoria" + "\t");  
				msgInfo.append("transaccion : "+registroRequest.getTransaccion()+ "\t");
				msgInfo.append("servicio : "+registroRequest.getServicio()+ "\t");
				msgInfo.append("ipCliente : "+registroRequest.getIpCliente()+ "\t");
				msgInfo.append("nombreCliente : "+registroRequest.getNombreCliente()+ "\t");
				msgInfo.append("ipServidor : "+registroRequest.getIpServidor()+ "\t");
				msgInfo.append("nombreServidor : "+registroRequest.getNombreServidor()+ "\t");
				msgInfo.append("cuentaUsuario : "+registroRequest.getCuentaUsuario()+ "\t");
				msgInfo.append("telefono : "+registroRequest.getTelefono()+ "\t");
				msgInfo.append("monto : "+registroRequest.getMonto()+ "\t");
				msgInfo.append("texto : "+registroRequest.getTexto()+ "\t");
		        msgInfo.append("Return [Estado : " + registroResponse.getEstado()+ ",\t");
		        msgInfo.append("Resultado : " + registroResponse.getResultado() + "]\t");
		        msgInfo.append((endTime - startTime) + "ms\t");
		        logger.info(msgInfo.toString());
		        msgInfo=null;
			
			}else {
				  msgInfo.append("leerOpcionesPorUsuario" + "\t");
				  msgInfo.append("transaccion : "+registroRequest.getTransaccion()+ "\t");
				  msgInfo.append("servicio : "+registroRequest.getServicio()+ "\t");
				  msgInfo.append("ipCliente : "+registroRequest.getIpCliente()+ "\t");
				  msgInfo.append("nombreCliente : "+registroRequest.getNombreCliente()+ "\t");
				  msgInfo.append("ipServidor : "+registroRequest.getIpServidor()+ "\t");
				  msgInfo.append("nombreServidor : "+registroRequest.getNombreServidor()+ "\t");
				  msgInfo.append("cuentaUsuario : "+registroRequest.getCuentaUsuario()+ "\t");
				  msgInfo.append("telefono : "+registroRequest.getTelefono()+ "\t");
				  msgInfo.append("monto : "+registroRequest.getMonto()+ "\t");
				  msgInfo.append("texto : "+registroRequest.getTexto()+ "\t");
			      msgInfo.append("NO OK Response is null" + "\t");
				  msgInfo.append((endTime - startTime) + "ms\t");
				  logger.info(msgInfo.toString());
				  registroResponse.setEstado("-1");
				  registroResponse.setResultado("NO OK Response is null");
				  msgInfo=null;
			   }
			
		}catch(IOException ioex){
			endTime = System.currentTimeMillis();
			msgInfo.append("ws-registroAuditoria" + "\t");
			msgInfo.append("[" + registroRequest.getTransaccion() + ","+ registroRequest.getServicio()+", "+registroRequest.getIpCliente()+", "+registroRequest.getNombreCliente()+", "+registroRequest.getIpServidor()+
					", "+registroRequest.getNombreServidor()+", "+registroRequest.getCuentaUsuario()+", "+registroRequest.getTelefono()+", "+registroRequest.getMonto()+", "+registroRequest.getTexto()+"]" + "\n");			
	        msgInfo.append("No OK\t");
	        msgInfo.append("IOException=" + ioex.getMessage() + "\t");
	        msgInfo.append((endTime - startTime) + "ms\n"); 
	        logger.info(msgInfo.toString());
	        registroResponse.setEstado("-1");
	        registroResponse.setResultado("IOException=" + ioex.getMessage());
	        msgInfo=null;
		}catch (SOAPException soapex) {
			endTime = System.currentTimeMillis();
			if(soapex.toString().contains("Message send failed")){
				msgInfo.append("ws-registroAuditoria" + "\t");
				msgInfo.append("[" + registroRequest.getTransaccion() + ","+ registroRequest.getServicio()+", "+registroRequest.getIpCliente()+", "+registroRequest.getNombreCliente()+", "+registroRequest.getIpServidor()+
						", "+registroRequest.getNombreServidor()+", "+registroRequest.getCuentaUsuario()+", "+registroRequest.getTelefono()+", "+registroRequest.getMonto()+", "+registroRequest.getTexto()+"]" + "\n");			
		        msgInfo.append("No OK\t");
		        msgInfo.append("TimeOut SOAPException=" + soapex.getMessage() + "\t");
		        msgInfo.append((endTime - startTime) + "ms\n"); 
		        logger.info(msgInfo.toString());
		        registroResponse.setEstado("-1");
		        registroResponse.setResultado("TimeOut SOAPException=" + soapex.getMessage());
		        msgInfo=null;
	        }else{
				msgInfo.append("ws-registroAuditoria" + "\t");
				msgInfo.append("[" + registroRequest.getTransaccion() + ","+ registroRequest.getServicio()+", "+registroRequest.getIpCliente()+", "+registroRequest.getNombreCliente()+", "+registroRequest.getIpServidor()+
						", "+registroRequest.getNombreServidor()+", "+registroRequest.getCuentaUsuario()+", "+registroRequest.getTelefono()+", "+registroRequest.getMonto()+", "+registroRequest.getTexto()+"]" + "\n");			
		       	msgInfo.append("No OK\t");
		        msgInfo.append("SOAPException=" + soapex.getMessage() + "\t");
		        msgInfo.append((endTime - startTime) + "ms\n"); 
		        registroResponse.setEstado("-1");
		        registroResponse.setResultado("SOAPException=" + soapex.getMessage());
		        logger.info(msgInfo.toString());
		        msgInfo=null;
	        }
		}catch (Exception ex) {
			endTime = System.currentTimeMillis();
			msgInfo.append("ws-registroAuditoria" + "\t");
			msgInfo.append("[" + registroRequest.getTransaccion() + ","+ registroRequest.getServicio()+", "+registroRequest.getIpCliente()+", "+registroRequest.getNombreCliente()+", "+registroRequest.getIpServidor()+
					", "+registroRequest.getNombreServidor()+", "+registroRequest.getCuentaUsuario()+", "+registroRequest.getTelefono()+", "+registroRequest.getMonto()+", "+registroRequest.getTexto()+"]" + "\n");			
	        msgInfo.append("No OK\t");
	        msgInfo.append("Exception=" + ex.getMessage() + "\t");
	        msgInfo.append((endTime - startTime) + "ms\n"); 
	        logger.info(msgInfo.toString()); 
	        registroResponse.setEstado("-1");
	        registroResponse.setResultado("Exception=" + ex.getMessage());
	        msgInfo=null;
		}finally{
			conn.close(); // close connection
			conn = null;
		}
		return registroResponse;
	}
	
	public void init() throws Exception{
		try{
			logger.info("Initializing RegistroAuditoriaManager Web Service Manager...");
			logger.info("RegistroAuditoriaManager Web Service Address = " + address);
			logger.info("RegistroAuditoriaManager Web Service Port = " + port);
			logger.info("RegistroAuditoriaManager Web Service = " + service);
			url = "http://"+ address+":"+port+"/"+service;
			logger.info("RegistroAuditoriaManager URL = "+url);
			logger.info("RegistroAuditoriaManager Web Service Manager initialized successfully");
		} catch (Exception _ex) {
			_ex.printStackTrace();
			throw new Exception("Unable to initialize RegistroAuditoriaManager webservice manager");
		}
	}
}
